package org.openlab.webapp.controller;

import java.io.Reader;
import java.io.StringReader;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import lombok.AllArgsConstructor;
import lombok.Data;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.openlab.model.ExchangeAttribute;
import org.openlab.model.ExchangeMapping;
import org.openlab.service.ExchangeAttributeService;
import org.openlab.service.ExchangeMappingService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

@Controller
@RequestMapping("/exchangeMapping")
public class ExchangeMappingController {
	@Autowired
	private ExchangeMappingService exService;
	@Autowired
	private ExchangeAttributeService attrService;

	@RequestMapping()
	public ModelAndView main(ModelMap model) {
		model.put("exchanges", exService.getAllDistinct());
		return new ModelAndView("allExchanges");
	}
	
	
	@RequestMapping(value="/edit", method = RequestMethod.GET)
	public ModelAndView editGet(@RequestParam("id") long id, ModelMap model) {
		ExchangeMapping ex = exService.get(id);
		if (ex == null) {
			ex = ExchangeMapping.newExchangeMapping();
		}
		model.put("exchangeMapping", ex);
		return new ModelAndView("exchangeForm");
	}

	@RequestMapping(value="/import", method = RequestMethod.GET)
	public ModelAndView importGet(ModelMap model) {
		return new ModelAndView("exchangeImportForm");
	}
	@RequestMapping(value="/import", method = RequestMethod.POST)
	public ModelAndView importPost(ModelMap model, HttpServletRequest request) {
		ExchangeMapping dx = ExchangeMapping.newExchangeMapping();
		dx.setAttributes(ExchangeAttribute.importing(request));
		model.put("exchangeMapping", dx);
		
		return new ModelAndView("exchangeForm");
	}

	
	@RequestMapping(value="/save", method = RequestMethod.POST)
	public ModelAndView edit(ModelMap model, HttpServletRequest request,
            @ModelAttribute("exchangeMapping") ExchangeMapping ex) {
		ex.setAttributes(ExchangeAttribute.extract(request));
		exService.save(ex);
		
		return new ModelAndView("redirect:/open/exchangeMapping");
	}
	
	@SuppressWarnings("unchecked")
	@RequestMapping(value="/validate", method = RequestMethod.POST)
	public ModelAndView validat(ModelMap model,
			@RequestParam("id") long id,
			@RequestParam("target") String target,
			@RequestParam("ifXml") String ifXml) {
		boolean validateSender = ("Sender").equals(target);
		ExchangeMapping ex = exService.get(id);
		SAXBuilder builder = new SAXBuilder();
		Reader xml = new StringReader(ifXml);
		List<AttrResult> result = Lists.newArrayList();
		try {
			Document doc = builder.build(xml);
			Element root = doc.getRootElement();
			Element exDef = root.getChild("PSCOPE_CLASSES").getChild("Row");
			String commodity = exDef.getAttributeValue("RDM_COMMODITY_NAME");
			String sendTable = exDef.getAttributeValue("SEND_TABLE_NAME");
			String recvTable = exDef.getAttributeValue("RECEIVE_TABLE_NAME");
			if (!ex.getCommodity().equals(commodity)) {
				model.put("commodity", "Commodity mismatch ("+ex.getCommodity()+" -> "+commodity+")");
			}
			if (validateSender) {
				if (!ex.getFromTable().equals(sendTable)) {
					model.put("table", "Sender table mismatch ("+ex.getFromTable()+" -> "+sendTable+")");
				}
			} else {
				if (!ex.getToTable().equals(recvTable)) {
					model.put("table", "Receiver table mismatch ("+ex.getToTable()+" -> "+recvTable+")");
				}
			}
			
			
			Element attrs = root.getChild("PSCOPE_PROPERTIES");
			Map<String, Element> attrLookup = Maps.newHashMap();
			for (Element row : (List<Element>)attrs.getChildren("Row")) {
				attrLookup.put(row.getAttributeValue("RDM_ATTRIBUTE_NAME"), row);
			}
			

			
			// validate attributes
			for (ExchangeAttribute attr : ex.getAttributeList()) {
				String rdm = attr.getRdm();
				Element row = attrLookup.get(rdm);
				String res = "";
				if (row == null) {
					result.add(new AttrResult(rdm, "attribute missing"));
				} else {
					if (attr.isPrimaryKey()^("Y").equals(row.getAttributeValue("IS_PROPERTY_UNIQUE_KEY"))) {
						res += "Primary Key mismatch<br/>";
					}
					boolean x = attr.isTransactable();
					boolean y=("Y").equals(row.getAttributeValue("IS_PROPERTY_TRANSACTABLE"));
					if (x^y) {
						res += "Transactable mismatch<br/>";
					}
					
					//=== sender
					String sender = attr.getSender();
					if ("COLUMN".equals(attr.getSenderType())) {
						if (row.getAttribute("COLUMN_NAME_OUT") == null || !sender.equals(row.getAttributeValue("COLUMN_NAME_OUT"))) {
							res += "Column out missing or mismatch<br/>";
						}
					} else {
						if (row.getAttribute("DEFAULT_VALUE_OUT") == null || !sender.equals(row.getAttributeValue("DEFAULT_VALUE_OUT"))) {
							res += "Defualt value missing or mismatch<br/>";
						}
					}
					result.add(new AttrResult(rdm, res));
					
					//=== receiver
				}
			}
		} catch (Exception e) {
			
		}
		
		Collections.sort(result, new Comparator<AttrResult>() {
			@Override
			public int compare(AttrResult a1, AttrResult a2) {
				return a1.getRdm().compareTo(a2.getRdm());
			}
			
		});
		model.put("result", result);
		return new ModelAndView("dxResult");
	}
	
	@Data
	@AllArgsConstructor
	public static class AttrResult {
		private String rdm;
		private String result;
	}
}
